<template>
  <el-dialog
    v-model="state.dialogFormVisible"
    :title="t('account.accountInfo')"
    custom-class="dialog-min-width"
    @close="onDialogClose"
    :destroy-on-close="true"
  >
    <el-form ref="formRef" :model="formEdit" :rules="rules" label-width="120px">
      <el-row>
        <el-col :lg="12" :md="12" :sm="24" :xs="24">
          <el-form-item :label="t('account.name')" prop="name">
            <el-input v-model="formEdit.name" maxlength="30" clearable>
            </el-input>
          </el-form-item>
        </el-col>
        <el-col :lg="12" :md="12" :sm="24" :xs="24">
          <el-form-item :label="t('account.gender')">
            <el-radio-group v-model="formEdit.gender">
              <el-radio-button :label="1">{{
                t("account.genderMale")
              }}</el-radio-button>
              <el-radio-button :label="0">{{
                t("account.genderFemale")
              }}</el-radio-button>
              <el-radio-button :label="2">{{
                t("account.genderUnknown")
              }}</el-radio-button>
            </el-radio-group>
          </el-form-item>
        </el-col>

        <el-col :lg="12" :md="12" :sm="24" :xs="24">
          <el-form-item :label="t('account.account')" prop="account">
            <el-input v-model="formEdit.account" maxlength="30" clearable>
            </el-input>
          </el-form-item>
        </el-col>
        <el-col :lg="12" :md="12" :sm="24" :xs="24">
          <el-form-item :label="t('account.employeeNumber')">
            <el-input
              v-model="formEdit.employeeNumber"
              maxlength="30"
              clearable
            >
            </el-input>
          </el-form-item>
        </el-col>
        <el-col :lg="12" :md="12" :sm="24" :xs="24" v-if="state.addAccount">
          <el-form-item :label="t('account.password')" prop="password1">
            <el-input
              v-model="state.password1"
              :type="type1"
              @focus="type1 = 'password'"
              show-password
              minlength="8"
              maxlength="16"
              autocomplete="new-password"
              clearable
              onkeypress="capsLockOn($event)"
            >
            </el-input>
          </el-form-item>
        </el-col>
        <el-col :lg="12" :md="12" :sm="24" :xs="24" v-if="state.addAccount">
          <el-form-item
            :label="t('account.confirmPassword')"
            prop="password2"
            :class="store.appLocale == 'en_US' ? 'break-label' : ''"
          >
            <el-input
              v-model="state.password2"
              :type="type2"
              @focus="type2 = 'password'"
              show-password
              minlength="8"
              maxlength="16"
              autocomplete="new-password"
              clearable
            >
            </el-input>
          </el-form-item>
        </el-col>

        <el-col :lg="12" :md="12" :sm="24" :xs="24">
          <el-form-item :label="t('account.birthday')">
            <el-date-picker
              v-model="state.birthday"
              type="date"
              class="fix-el-date-picker-width"
              style="width: 100%"
            />
          </el-form-item>
        </el-col>
        <el-col :lg="12" :md="12" :sm="24" :xs="24">
          <el-form-item :label="t('account.idNumber')">
            <el-input v-model="formEdit.idNumber" maxlength="18" clearable>
            </el-input>
          </el-form-item>
        </el-col>
        <el-col :lg="12" :md="12" :sm="24" :xs="24">
          <el-form-item :label="t('account.email')" prop="email">
            <el-input v-model="formEdit.email" maxlength="128" clearable>
            </el-input>
          </el-form-item>
        </el-col>
        <el-col :lg="12" :md="12" :sm="24" :xs="24">
          <el-form-item :label="t('account.mobile')">
            <el-input v-model="formEdit.mobile" maxlength="11" clearable>
            </el-input>
          </el-form-item>
        </el-col>

        <el-col :lg="24" :md="24" :sm="24" :xs="24">
          <el-form-item :label="t('account.orgName')" prop="orgPaths">
            <el-cascader
              v-if="state.dialogFormVisible"
              ref="orgRef"
              :props="orgProps"
              show-all-levels
              clearable
              class="fix-el-cascader-width-100"
              @change="onOrgCascaderChange"
              v-model="formEdit.orgPaths"
            />
          </el-form-item>
        </el-col>
        <el-col :lg="24" :md="24" :sm="24" :xs="24">
          <el-form-item :label="t('account.deptName')">
            <el-cascader
              v-if="state.dialogFormVisible"
              ref="deptRef"
              :props="deptProps"
              show-all-levels
              clearable
              class="fix-el-cascader-width-100"
              @change="onDeptCascaderChange"
              v-model="formEdit.deptPaths"
              :options="state.deptRefesh"
            />
          </el-form-item>
        </el-col>

        <el-col :lg="24" :md="24" :sm="24" :xs="24">
          <el-form-item :label="t('account.status')">
            <el-switch
              v-model="formEdit.status"
              :active-value="1"
              :inactive-value="0"
            />
          </el-form-item>
        </el-col>
        <el-col :lg="24" :md="24" :sm="24" :xs="24">
          <el-form-item :label="t('account.description')">
            <el-input
              v-model="formEdit.description"
              type="textarea"
              maxlength="64"
            >
            </el-input>
          </el-form-item>
        </el-col>
        <el-col :lg="24" :md="24" :sm="24" :xs="24">
          <el-form-item :label="t('account.roles')">
            <template v-for="category in state.roleCategory">
              <div style="display: block; width: 100%">
                <el-checkbox
                  v-model="category.value"
                  :indeterminate="category.isIndeterminate"
                  @change="handleCheckAllChange($event, category)"
                >
                  <span style="font-weight: bold">{{ category.name }}</span>
                </el-checkbox>
              </div>
              <el-checkbox-group
                v-model="category.checkedRoleIds"
                @change="handleCheckedCitiesChange($event, category)"
              >
                <template v-for="role in state.allRoles">
                  <el-checkbox
                    v-if="role.category == category.name"
                    :key="role.roleId"
                    :label="role.roleId"
                    >{{ role.roleName }}</el-checkbox
                  >
                </template>
              </el-checkbox-group>
              <el-divider />
            </template>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="state.dialogFormVisible = false">{{
          t("common.cancelButton")
        }}</el-button>
        <el-button type="primary" @click="handleSubmit">{{
          t("common.submitButton")
        }}</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { reactive, ref } from "vue";
import { useStore } from "../../../stores/store";
import utils from "../../../utils/utils";
import moment from "moment";
import apiAccount from "../api/account";
import apiRole from "../api/role";
import apiOrganization from "../api/organization";
import OrgTreeNode from "../organization/tree-node";
import { useI18n } from "vue-i18n";
const { t } = useI18n({ useScope: "global" });
const emit = defineEmits<{
  (event: "on-submit-success", row: any): void;
}>();

const store = useStore();
const formRef = ref();
const publicKey = ref("");
const type1 = ref("");
const type2 = ref("");
const orgRef = ref();
const deptRef = ref();

const stateOriginal = () =>
  reactive({
    dialogFormVisible: false,
    // true 新增、false 修改账号
    addAccount: true,
    allRoles: Array<any>(),
    roleCategory: Array<any>(),
    password1: "",
    password2: "",
    birthday: "",
    // 强制刷新，用于选择了单位后，清除部门数据，或者在修改数据回显时触发
    deptRefesh: Array<OrgTreeNode>(),
  });
const state = reactive(stateOriginal());

const formEditOriginal = () => {
  return {
    sessionId: "",
    accountId: "",
    account: "",
    encryptedPassword: "",
    // 凭证类型
    category: "ACCOUNT",
    name: "",
    gender: 2,
    employeeNumber: "",

    orgName: "",
    orgCode: "",

    deptName: "",
    deptCode: "",
    status: 1,
    idNumber: "",
    email: "",
    mobile: "",
    birthday: "",
    description: "",
    // 前台临时使用，用于还原下来树状态
    // orgId: "",
    // 提交数据库，逗号分隔字符串
    orgPath: "",
    // 前台临时使用，绑定下拉树
    orgPaths: Array<string>(),
    // deptId: "",
    deptPath: "",
    deptPaths: Array<string>(),
    // 账号最初读取的角色信息
    roles: Array<any>(),
    // 账号最终选中的角色，提交的数据
    roleIds: Array<string>(),
  };
};
const formEdit = reactive(formEditOriginal());

const rules = reactive({
  name: [
    { required: true, message: () => t("common.required"), trigger: "blur" },
  ],
  account: [
    {
      required: true,
      message: () => t("common.required"),
      trigger: "blur",
    },
  ],
  orgPaths: [
    {
      required: true,
      message: () => t("common.select"),
      trigger: "change",
    },
  ],
  password1: [
    {
      validator: (rule: any, value: any, callback: any) => {
        // console.log("password1 validator", value);
        // 由于 password1 未绑定到 formEdit 所以 value 取不到值，直接使用 state.password1
        if (state.password1 === "") {
          callback(new Error(t("common.required")));
        } else {
          callback();
        }
      },
      trigger: "blur",
      required: true,
    },
  ],
  password2: [
    {
      validator: (rule: any, value: any, callback: any) => {
        // console.log("password2 validator", value);
        if (state.password2 === "") {
          callback(new Error(t("common.required")));
        } else if (state.password2 !== state.password1) {
          callback(new Error(t("account.passwordInconsistent")));
        } else {
          callback();
        }
      },
      trigger: "blur",
      required: true,
    },
  ],
  email: [
    {
      type: "email",
      message: () => t("account.emailVerificationFailed"),
      trigger: ["blur", "change"],
    },
    // {
    //   validator: function (rule, value, callback) {
    //     if (
    //       /^([a-zA-Z0-9]+[-|_|.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[-|_|.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/.test(
    //         value
    //       ) == false
    //     ) {
    //       callback(new Error(t("account.emailVerificationFailed")));
    //     } else {
    //       //校验通过
    //       callback();
    //     }
    //   },
    //   trigger: "blur",
    // },
  ],
});

const orgProps = {
  label: "orgName",
  value: "orgId",
  leaf: "leaf",
  checkStrictly: true,
  lazy: true,
  async lazyLoad(node: any, resolve: any) {
    if (node.level === 0) {
      let childs = await apiOrganization.loadChilds("0", "单位");
      let orgNodes = Array<OrgTreeNode>();
      Object.assign(orgNodes, childs);
      return resolve(orgNodes);
    } else {
      if (node.data.leaf) {
        resolve([]);
      }
      let childs = await apiOrganization.loadChilds(node.data.orgId, "单位");
      let orgNodes = Array<OrgTreeNode>();
      Object.assign(orgNodes, childs);
      return resolve(orgNodes);
    }
  },
};

const deptProps = {
  label: "orgName",
  value: "orgId",
  leaf: "leaf",
  checkStrictly: true,
  lazy: true,
  async lazyLoad(node: any, resolve: any) {
    if (node.level === 0) {
      let parentId = formEdit.orgPaths[formEdit.orgPaths.length - 1];
      let childs = await apiOrganization.loadChilds(parentId, "部门");
      let orgNodes = Array<OrgTreeNode>();
      Object.assign(orgNodes, childs);
      return resolve(orgNodes);
    } else {
      if (node.data.leaf) {
        resolve([]);
      }
      let childs = await apiOrganization.loadChilds(node.data.orgId, "部门");
      let orgNodes = Array<OrgTreeNode>();
      Object.assign(orgNodes, childs);
      return resolve(orgNodes);
    }
  },
};

const onOrgCascaderChange = (value: any) => {
  // 单选情况下获取选中数据，value 仅对应 prop 中的 value 即 orgId，信息有限
  // console.log("onOrgCascaderChange", orgRef.value.getCheckedNodes()[0].data);
  formEdit.orgCode = orgRef.value.getCheckedNodes()[0].data.orgCode;
  formEdit.orgName = orgRef.value.getCheckedNodes()[0].data.orgName;
  // 通过重置数据源清空部门选项，点击下拉时会通过 deptProps 的懒加载重新请求数据
  state.deptRefesh = Array<OrgTreeNode>();
};
const onDeptCascaderChange = (value: any) => {
  // console.log("onDeptCascaderChange", value);
  formEdit.deptCode = deptRef.value.getCheckedNodes()[0].data.orgCode;
  formEdit.deptName = deptRef.value.getCheckedNodes()[0].data.orgName;
};

const handleCheckAllChange = (value: any, category: any) => {
  // console.log("handleCheckAllChange", value, category);
  let checkedRoleIds = Array<string>();
  if (value) {
    // 全选
    state.allRoles.forEach((m) => {
      if (m.category == category.name) {
        checkedRoleIds.push(m.roleId);
      }
    });
  } else {
    category.value = false;
  }
  category.checkedRoleIds = checkedRoleIds;
  // 取消中间状态
  category.isIndeterminate = false;
};
const handleCheckedCitiesChange = (value: any, category: any) => {
  // console.log("handleCheckedCitiesChange", value, category);
  // 判断三种情况，全选、全部取消、中间状态
  // 全部可选数量
  let categoryCnt = 0;
  state.allRoles.forEach((m) => {
    if (m.category == category.name) {
      categoryCnt++;
    }
  });
  // 已选中数量
  let categoryCheckedCnt = category.checkedRoleIds.length;

  category.value = categoryCnt === categoryCheckedCnt;
  category.isIndeterminate =
    categoryCheckedCnt > 0 && categoryCheckedCnt < categoryCnt;
};

const handleSubmit = async () => {
  await formRef.value.validate();

  // formEdit.orgId = "";
  if (formEdit.orgPaths.length > 0) {
    // formEdit.orgId = formEdit.orgPaths[formEdit.orgPaths.length - 1];
    formEdit.orgPath = formEdit.orgPaths.join(",");
  }

  // formEdit.deptId = "";
  if (formEdit.deptPaths.length > 0) {
    // formEdit.deptId = formEdit.deptPaths[formEdit.deptPaths.length - 1];
    formEdit.deptPath = formEdit.deptPaths.join(",");
  }

  let roleIds = Array<string>();
  state.roleCategory.forEach((m) => {
    m.checkedRoleIds.forEach((n: string) => {
      roleIds.push(n);
    });
  });
  formEdit.roleIds = roleIds;
  // console.log("handleSubmit", typeof state.birthday, state.birthday == "");
  // 第一次 ""，后续修改为 object
  if (state.birthday == "" || state.birthday == null) {
    // formEdit.birthday = moment().format("YYYY-MM-DD");
    formEdit.birthday = "";
  } else if (typeof state.birthday == "object") {
    formEdit.birthday = moment(state.birthday).format("YYYY-MM-DD");
  }

  // 加密数据，清理原文
  formEdit.encryptedPassword = utils.doSm2Encrypt(
    publicKey.value || "",
    state.password1
  );

  // 处理业务逻辑，触发关闭事件
  apiAccount
    .updateAccount(formEdit)
    .then((response: any) => {
      if (response.data.code == 200) {
        state.dialogFormVisible = false;
        utils.infoNotification(t("common.submitSuccess"));
        emit("on-submit-success", formEdit);
      }
    })
    .catch((err: any) => {
      // 还原原文
      utils.errorNotification(t("common.submitException"), err);
    });
};

const show = (row: any) => {
  // console.log("show", row);
  // 测试代码，初始化组织机构下拉树
  // formEdit.orgPath = ["root-root", "shanghai"];
  // formEdit.deptPath = ["shanghai1", "shanghai12"];
  Object.assign(state, stateOriginal());
  Object.assign(formEdit, formEditOriginal());
  if (row != undefined) {
    // 修改
    state.addAccount = false;
    let model = null;
    apiAccount
      .getAccount(row.accountId)
      .then((response: any) => {
        if (response.data.code == 200) {
          model = response.data.data;
          Object.assign(formEdit, model);

          apiAccount
            .getAccountExtension(row.accountId)
            .then((response: any) => {
              if (response.data.code == 200) {
                Object.assign(formEdit, response.data.data);
                if (formEdit.orgPath.length > 0) {
                  formEdit.orgPaths = formEdit.orgPath.split(",");
                }
                if (formEdit.deptPath.length > 0) {
                  formEdit.deptPaths = formEdit.deptPath.split(",");
                }
                // console.log("show getAccount", formEdit);

                state.birthday = formEdit.birthday;

                // 数据回显是通过 v-model，配合懒加载自动实现的，通过赋值 v-model，自动一级一级多次请求回显数据
                // 强制刷新，单位节点确定后，初始化部门下拉树，由于 Cascader 是页面一加载就触发懒加载获取数据，此时 formEdit.orgPath 根节点数据还没有初始化好，所以无法读取数据
                // state.orgRefesh = Array<OrgTreeNode>();
                state.deptRefesh = Array<OrgTreeNode>();
              }
            })
            .catch((err: any) => {
              utils.errorNotification(t("common.submitException"), err);
            });

          apiAccount
            .queryAccountRole(row.accountId)
            .then((response: any) => {
              if (response.data.code == 200) {
                // Object.assign(formEdit, response.data.data);
                response.data.data.forEach((m: any) => {
                  formEdit.roles.push(m);
                });
                // console.log("queryAccountRole", formEdit.roles);
                // 查询全部角色，并选中已选角色
                queryAllRole();
              }
            })
            .catch((err: any) => {
              utils.errorNotification(t("common.submitException"), err);
            });
        }
      })
      .catch((err: any) => {
        utils.errorNotification(t("common.submitException"), err);
      });
  } else {
    formEdit.accountId = utils.getUUID();
    // 查询全部角色
    queryAllRole();
  }
  getPublicKey();
  state.dialogFormVisible = true;
  // 重置表单校验
  if (formRef.value) {
    formRef.value.resetFields();
  }
};

const onDialogClose = () => {
  // state.deptRefesh = false;
};

const getPublicKey = () => {
  formEdit.sessionId = utils.getUUID();
  apiAccount
    .generateSessionPublicKeyQ(formEdit.sessionId)
    .then((response: any) => {
      if (response.data.code == 200) {
        publicKey.value = response.data.data;
      }
    })
    .catch((err: any) => {
      utils.errorNotification(t("common.submitException"), err);
    });
};

const queryAllRole = () => {
  apiRole
    .queryAllRole()
    .then((response: any) => {
      if (response.data.code == 200 && response.data.data != "") {
        state.allRoles = response.data.data;
        // 识别出所有分类
        let roleCategory = Array<any>();
        state.allRoles.forEach((m) => {
          let exists = false;
          roleCategory.forEach((c) => {
            if (c.name == m.category) {
              exists = true;
            }
          });

          if (!exists) {
            roleCategory.push({
              name: m.category,
              value: false,
              isIndeterminate: false,
              checkedRoleIds: Array<string>(),
            });
          }
        });

        // 处理每个分类的默认选中
        roleCategory.forEach((c) => {
          let checkedRoleIds = Array<string>();
          state.allRoles.forEach((m) => {
            if (c.name == m.category) {
              formEdit.roles.forEach((r) => {
                // console.log("roleCategory.forEach", r, m);
                if (r.category == c.name && r.roleCode == m.roleCode) {
                  // 默认选中
                  checkedRoleIds.push(m.roleId);
                  // console.log(
                  //   "roleCategory.forEach -> formEdit.roles.forEach",
                  //   checkedRoleIds
                  // );
                }
              });
            }
          });
          c.checkedRoleIds = checkedRoleIds;
        });

        state.roleCategory = roleCategory;
        // console.log("queryAllRole", state.roleCategory);
      }
    })
    .catch((err: any) => {
      utils.errorNotification(t("common.submitException"), err);
    });
};

defineExpose({
  show,
});
</script>
<style lang="scss"></style>
